
/***************************************************************/
/*     import.cpp     Functions for importing art/palettes     */
/*                    By: Josh Fiorio                          */
/***************************************************************/

#include "import.h"

extern long pcolor;    /* TODO: pass as an arg to the functions */
extern int artMag;     /* TODO: same as up above =) */

void BitmapToBuf(char fn[], FrameBuffer &buf, palette &it, int mode, 
                      int top, int left, int bottom, int right)
{
	//declare file and open
	FILE *bf;
	bf=fopen(fn, "r+b");

	//declare vars.
	char head[3]="";
	int width, height;
	short bpp = 0;
    long bpos=0;
 
	//go to beginning and get header
	rewind(bf);
	//fseek(bf, bpos, 0);
	fread(&head, 2, 1, bf);
		bpos=bpos+2;
		fseek(bf, bpos, 0);

	//if we don't have a bmp file here, then just stop
	if (strcmp(head, "BM") != 0) { return; }

	//read width
	bpos = 0x12;
	     fseek(bf, bpos, 0);
	     fread(&width, 4, 1, bf);
	     
    //read height
    bpos = 0x16;
         fseek(bf, bpos, 0);
         fread(&height, 4, 1, bf);
         
    //read bits per pixel
    bpos = 0x1c;
         fseek(bf, bpos, 0);
         fread(&bpp, 2, 1, bf);
    
    //if our bitmap is not 24 bits, then stop
	if (bpp != 24) { return; }

    
	//declare vars.
	short pixels[100][100];
	BYTE R, G, B = 0;
	int numpad=0;
	int ylp=0;

	//get the pixels
	if (bottom == -20)
	{
		for (ylp=0; ylp<=(height-1); ylp++)
		{
			for (int xlp=0; xlp<=(width-1); xlp++)
			{
				fread(&B, sizeof(B), 1, bf);
					bpos=bpos+sizeof(B);
					fseek(bf, bpos, 0);	
				fread(&G, sizeof(G), 1, bf);
					bpos=bpos+sizeof(G);
					fseek(bf, bpos, 0);
				fread(&R, sizeof(R), 1, bf);
					bpos=bpos+sizeof(R);
					fseek(bf, bpos, 0);	
			
				*(*pixels+((xlp+(ylp*width))))=c256to32(RGB(R,G,B));
			}	//end for

			numpad=(4-((width*3)%4));
			if (numpad>=4) {numpad=0;}

			bpos=bpos+numpad;
				fseek(bf, bpos, 0);
		}	//end for
	}	//end if

	//For portions:
	else
	{
		//Get old width of picture
		int ow=width;
		int oh=height;
		
		//Determine how many bytes to pad after each scanline
		numpad=(4-((ow*3)%4));
		if (numpad>=4) {numpad=0;}

		//Go to pixel portion that is the bottom of our rect
		bpos=bpos+(((oh-bottom)*(ow))*3);
		bpos=bpos+((oh-bottom)*numpad);
		fseek(bf, bpos, 0);

		//Get our new width & height
		height=bottom-top;
		width=right-left;

		//Start reading pixels
		for (ylp=0; ylp<=(height-1); ylp++)
		{
			//Skip pixels for the left portion of our rect
			bpos=bpos+(left*3);
			fseek(bf, bpos, 0);

			//Read the pixels 
			for (int xlp=0; xlp<=width-1; xlp++)
			{
				fread(&B, sizeof(B), 1, bf);
					bpos=bpos+sizeof(B);
					fseek(bf, bpos, 0);	
				fread(&G, sizeof(G), 1, bf);
					bpos=bpos+sizeof(G);
					fseek(bf, bpos, 0);
				fread(&R, sizeof(R), 1, bf);
					bpos=bpos+sizeof(R);
					fseek(bf, bpos, 0);	
			
				*(*pixels+((xlp+(ylp*width))))=c256to32(RGB(R,G,B));
			}	//end for

			//Skip pixels for the right potion of our rect
			bpos=bpos+((ow-right)*3);
			fseek(bf, bpos, 0);

			//Skip padded area as well
			bpos=bpos+numpad;
				fseek(bf, bpos, 0);
		}	//end for
	}	//end if
		

	//NOW, we have to make a new palette out of this
	//We obviously can't use 16 million colors for a palette
	//We need to get our priority colors first
	
	//declare arrays for holding color count data
	short cols[1000];
	short ccnt[1000];
	memset(cols, 0, sizeof(cols));
	memset(ccnt, 0, sizeof(ccnt));

	//declare vars.
	int nocols=0;
	int ylp2=0;
	int cclp=0;

	//get colors and their count
	for (ylp2=0; ylp2<=(height-1); ylp2++)
	{
		for (int xlp=0; xlp<=(width-1); xlp++)
		{
			for (cclp=0; cclp<=nocols; cclp++)
			{
				if (cols[cclp]==*(*pixels+((xlp+(ylp2*width)))) || (xlp==0 && ylp2==0))
				{
					ccnt[cclp]++;
					break;
				}	//end if
			}	//end for
			
			if (cclp > nocols)
			{
				cols[cclp]=*(*pixels+((xlp+(ylp2*width))));
				nocols=nocols+1;
			}	//end if
		}	//end for
	}	//end for

	//declare vars. for sorting color count data
	short rcols[1000];
	short rccnt[1000];
	memset(rcols, 0, sizeof(rcols));
	memset(rccnt, 0, sizeof(rccnt));

	//declare vars.
	int bc=0;

	//sort colors by count
	for (int a=0; a<=1000; a++)
	{
		for (int b=0; b<=1000; b++)
		{
			if (ccnt[b]>rccnt[a])
			{
				rccnt[a]=ccnt[b];
				rcols[a]=cols[b];
				bc=b;
			}	//end if
		}	//end for

		ccnt[bc]=0;
	}	//end for
	
	//update palette if got the arg to do so
	if (mode & BI_PRIORITY)
	{
		/*if (!mt)
		{*/
		for (int c=1; c<=15/*127*/; c++)
			it.colors[c]=rcols[c-1];
		//end for
		/*}
		else
		{
		for (int c=1; c<=127; c++)
			it.colors[c]=rcols[c-1];
		//end for
		}*/


	}	//end if

	//make 1st color in list, which is transparent in chaotix, transparent
	it.colors[0]=c256to32(pcolor);

	//So now we have the top priority pixel colors
	//we want to take the colors other than the first 15
	//and make them the color out of the first 15 that is
	//of the closest distance
	
	//declare vars.
	int ylp3=0;
	int a=0;

	//do this for each pixel
	for (ylp3=0; ylp3<=(height-1); ylp3++)
	{
		for (int xlp=0; xlp<=(width-1); xlp++)
		{ 
			/*if (!mt)
			{*/
			for (a=0; a<=15/*127*/; a++)
			{
				if (it.colors[a]==*(*pixels+((xlp+(ylp3*width)))))
					break;
				//end if
			}	//end for

			//if the color is not in our "palette"
			if (a>=16/*128*/)
			{
				//declare vars.
				int bigcol=0;
				double dif=RGB(255,255,255);

				//find the closest color to it
				for (int a=0; a<=15 /*127*/; a++)
				{
					//declare color holding vars.
					double r,g,b,r2,g2,b2=0;
					
					r = (*(*pixels+((xlp+(ylp3*width)))) & 31);
					g = ((*(*pixels+((xlp+(ylp3*width)))) >> 5) & 31);
					b = ((*(*pixels+((xlp+(ylp3*width)))) >> 10) & 31);
					
					r2 = (it.colors[a] & 31);
					g2 = ((it.colors[a] >> 5) & 31);
					b2 = ((it.colors[a] >> 10) & 31);

					if (pow(pow((r - r2),2) + pow((g - g2),2) + pow((b - b2),2),0.5)<dif)
					{
						dif = pow(pow((r - r2),2) + pow((g - g2),2) + pow((b - b2),2),0.5);
						bigcol=a;
					}	//end if
				}	//end for
				
				//set the pixel to the closest color
				*(*pixels+((xlp+(ylp3*width))))=it.colors[bigcol];
			}	//end if
			/*}
			else
			{			
			for (a=64; a<=127; a++)
			{
				if (it.colors[a]==*(*pixels+((xlp+(ylp3*width)))))
					break;
				//end if
			}	//end for

			//if the color is not in our "palette"
			if (a>=128)
			{
				//declare vars.
				int bigcol=0;
				double dif=RGB(255,255,255);

				//find the closest color to it
				for (int a=0; a<=127; a++)
				{
					//declare color holding vars.
					double r,g,b,r2,g2,b2=0;
					
					r = (*(*pixels+((xlp+(ylp3*width)))) & 31);
					g = ((*(*pixels+((xlp+(ylp3*width)))) >> 5) & 31);
					b = ((*(*pixels+((xlp+(ylp3*width)))) >> 10) & 31);
					
					r2 = (it.colors[a] & 31);
					g2 = ((it.colors[a] >> 5) & 31);
					b2 = ((it.colors[a] >> 10) & 31);

					if (pow(pow((r - r2),2) + pow((g - g2),2) + pow((b - b2),2),0.5)<dif)
					{
						dif = pow(pow((r - r2),2) + pow((g - g2),2) + pow((b - b2),2),0.5);
						bigcol=a;
					}	//end if
				}	//end for
				
				//set the pixel to the closest color
				*(*pixels+((xlp+(ylp3*width))))=it.colors[bigcol];
			}	//end if
			}*/
			
			//Clear buf before writing pixels to it
			//buf.Clear();

			//Write all our pixels to our buf
			for (int yp=0; yp<artMag; yp++)
			{
				for (int xp=0; xp<artMag; xp++)
				{
					buf.SetPixel((xlp*artMag)+xp,(((height-1)-ylp3)*artMag)+yp,c32to256(*(*pixels+((xlp+(ylp3*width))))));							
				}	//end for
			}	//end for	

		}	//end for
	}	//end for

	//Done with bitmap, close
	fclose(bf);
}	//end of func.


void UArtToBuf(char fn[], int wid, int hgt, FrameBuffer &buf, palette &it)
{
	//Create art file
	FILE *af2;
	af2=fopen(fn, "r+b");
	
	//declare vars.
	BYTE bte=0;
	short p1=0;
	short p2=0;
	long bpos=0;
	
	fseek(af2, bpos, 0);

    for (int tilex=0; tilex <= wid/*user type # of across tiles*/ - 1; tilex++)
	{
        for (int tiley=0; tiley <= hgt/*user type # of up&down tiles*/ - 1; tiley++)
		{
            for (int pixy=0; pixy <= 7; pixy++)
			{
				for (int pixx=0; pixx <= 7; pixx=pixx+2)
				{
                    //read 2 pixels
                    fread(&bte, sizeof(bte), 1, af2);
						bpos = bpos + sizeof(bte);
						fseek(af2, bpos, 0);
					
					//get 2 pixel values
					p1 = (short)((bte & 240)/16);
					p2 = (short)(bte & 15);
					//set the 2 pixels
					for (int yp=0; yp<artMag; yp++)
					{
						for (int xp=0; xp<artMag; xp++)
						{
							buf.SetPixel((((tilex * 8) + pixx)*artMag)+xp, (((tiley * 8) + pixy)*artMag)+yp, c32to256(it.colors[p1]));
							buf.SetPixel((((tilex * 8) + pixx + 1)*artMag)+xp, (((tiley * 8) + pixy)*artMag)+yp, c32to256(it.colors[p2]));
						}	//end for
					}	//end for

				}	//end for
			}	//end for
		}	//end for
	}	//end for

	fclose(af2);
}	//end of func.


void ROMArtViaSCToBuf(char fn1[], char fn2[], FrameBuffer &buf, palette &it)
{
	//Create ROM file to read from
	FILE *rf;
	rf=fopen(fn1, "r+b");

	//Create SC file to read from
	FILE *sf;
	sf=fopen(fn2, "r+t");

	//Declare vars.
    char *curLine=(char*)malloc(100);	//placeholder for current line in file
	int numtiles=0;						//placeholder for # of tiles in the art
	bool done=false;					//whether we have reached tile data yet

    while (!feof(sf) && !(done))
	{
		//get current line
		fgets(curLine, 100, sf);
		
		//if line is not a line like '$magenta' then
        if (strcmp(jsbstr(curLine, 0, 1), "$") != 0)
		{		
			if (strcmp(jsbstr(curLine, 0, 10), "TotalTiles") == 0)
				numtiles = atoi(jsbstr(curLine, 13, strlen(curLine) - 13));
			//end if
		}
		else
		{    
			if (strcmp(jsbstr(curLine, 1, 5), "Data:") == 0)
                done=true;
            //end if
		}	//end if
	}	//end while
	if (feof(sf)) {return;}
    
	//declare vars.
    int eqpos;				//placeholder for positions of char's in strings
    int tilex;				//placeholder for x position of a tile
    int tiley;				//placeholder for y position of a tile
    long rompos;			//placeholder for position of a tile in a rom
    bool magen=false;		//tells whether we are reading blank tiles or not

   while (!feof(sf))
   {
		//get current line
		fgets(curLine, 100, sf);
	    
		// if not a newline or a line like $magenta or $gray
		if (strcmp(jsbstr(curLine, 0, 1), "$") != 0 && strcmp(curLine, "\n") != 0)
		{
			//temp.
			char *e;

			//get proper x and y pos of tile
			eqpos = strchr(curLine, '=')-curLine;
			tilex = atoi(jsbstr(curLine, eqpos + 2, 1));
			eqpos = strchr(curLine+eqpos+1, ',')-curLine;
			tiley = atoi(jsbstr(curLine, eqpos + 2, 1));

			//if the tile isn't blank, then get it's pos
			if (!magen)
			{
				eqpos = strchr(curLine+eqpos+1, ',')-curLine;
				rompos = strtol(jsbstr(curLine, eqpos + 4, strlen(curLine)-(eqpos+4)), &e, 16);
			}
			else
				rompos = 0x50000;
			//end if
		
			//go to that pos in the actual rom
			fseek(rf, rompos, 0);

			//get the tile at that pos and write to both bufs at x&y pos
			for (int pixy=0; pixy<=7; pixy++)
			{
				for (int pixx=0; pixx<=7; pixx=pixx+2)
				{
					//get 2 pixels into 1 byte
					BYTE bte;
					fread(&bte, sizeof(bte), 1, rf);
						rompos=rompos+sizeof(bte);
						fseek(rf, rompos, 0);
					
					//get 2 pixel values
					short p1 = (short)((bte & 240)/16);
					short p2 = (short)(bte & 15);

					//set the 2 pixels onto the buf
					for (int yp=0; yp<artMag; yp++)
					{
						for (int xp=0; xp<artMag; xp++)
						{
							buf.SetPixel((((tilex * 8) + pixx)*artMag)+xp, (((tiley * 8) + pixy)*artMag)+yp, c32to256(it.colors[p1]));
							buf.SetPixel((((tilex * 8) + pixx + 1)*artMag)+xp, (((tiley * 8) + pixy)*artMag)+yp, c32to256(it.colors[p2]));
						}	//end for
					}	//end for

				}	//end for
			}	//end for

		}	//if it is like a '$Magenta' line then..
		else
		{
			//tell to set blank tiles for the rest
			if (strcmp(jsbstr(curLine, 1, 8), "Magenta:") == 0)
				magen=true;
			//end if
		}	//end if

   }	//end while

   //Close uneeded files
   fclose(rf);
   fclose(sf);

}	//end of func.

